﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;

namespace Notoric.Gui.Converters
{
    /// <summary>
    /// Converts a <see cref="ViewModel.Elements.Score"/> to a corresponding <see cref="FixedDocument"/>.
    /// </summary>
    [ValueConversion(typeof(ViewModel.Elements.Score), typeof(FixedDocument))]
    public class ScoreToFixedDocumentConverter : IValueConverter
    {
        #region IValueConverter Members

        /// <inheritdoc/>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is ViewModel.Elements.Score)
                return ConvertScoreToFixedDocument((ViewModel.Elements.Score)value);
            else
                return null;
        }

        /// <inheritdoc/>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Converts a page to a corresponding fixed page.
        /// </summary>
        /// <param name="page">Converted page</param>
        /// <returns>Created fixed page</returns>
        private PageContent ConvertPageToPageContent(ViewModel.Elements.Page page)
        {
            var content = new PageContent();
            var fixedPage = new FixedPage();

            fixedPage.Background = page.Background;
            fixedPage.Height = page.Height;
            fixedPage.Width = page.Width;
            fixedPage.ContentBox = new Rect(page.Margin.Left, page.Margin.Top, page.Width - page.Margin.Left - page.Margin.Top, page.Height - page.Margin.Top - page.Margin.Bottom);

            var border = new Border();
            border.BorderBrush = page.BorderBrush;
            border.BorderThickness = page.BorderThickness;
            fixedPage.Children.Add(border);

            FixedPage.SetLeft(border, page.Margin.Left);
            FixedPage.SetTop(border, page.Margin.Top);

            foreach (var section in page.Sections)
            {
                var sectionBorder = new Border();
                sectionBorder.Background = section.Background;
                sectionBorder.BorderBrush = section.BorderBrush;
                sectionBorder.BorderThickness = section.BorderThickness;
                sectionBorder.Height = section.Height;
                sectionBorder.Width = section.Width;
                sectionBorder.RenderTransform = new System.Windows.Media.RotateTransform(section.RotationAngle);

                var sectionContent = new ContentControl();
                if (section is ViewModel.Elements.ImageSection)
                {
                    var canvas = new Canvas();
                    canvas.Background = new ImageBrush(((ViewModel.Elements.DefaultImageSectionInterior)section.Interior).ImageSource);
                    sectionContent.Content = canvas;
                }
                else
                    sectionContent.Content = section.Interior;
                sectionContent.IsEnabled = false;

                sectionBorder.Child = sectionContent;
                fixedPage.Children.Add(sectionBorder);

                FixedPage.SetLeft(sectionBorder, section.Left);
                FixedPage.SetTop(sectionBorder, section.Top);
            }

            var sz = new Size(page.Width, page.Height);
            fixedPage.Measure(sz);
            fixedPage.Arrange(new Rect(new Point(), sz));
            fixedPage.UpdateLayout();

            ((IAddChild)content).AddChild(fixedPage);
            return content;
        }

        /// <summary>
        /// Converts a score to a corresponding fixed document.
        /// </summary>
        /// <param name="score">Converted score</param>
        /// <returns>Created fixed document</returns>
        private FixedDocument ConvertScoreToFixedDocument(ViewModel.Elements.Score score)
        {
            var document = new FixedDocument();

            foreach (var page in score.Pages)
                document.Pages.Add(ConvertPageToPageContent(page));

            return document;
        }

        #endregion
    }
}
